package scms;

import java.util.LinkedList;
import java.io.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;
import java.beans.*;

/**
 * Holds all inventory items
 * @author pumped
 */
public class Inventory {

	private LinkedList<InventoryItem> items = new LinkedList<InventoryItem>();
	private LinkedList<Product> products = new LinkedList<Product>();

	/**
	 * prints the items in the inventory
	 */
	public void printInventory() {
		System.out.println("\n--- Inventory ---");
		for (InventoryItem i : items) {
			i.print();
			i.printParts();
		}
		System.out.println("\n");

	}

	/**
	 * prints the prodcuts in the inventory
	 */
	public void printProducts() {
		System.out.println("\n--- Products ---");
		for (Product p : products) {
			p.print();
		}
		System.out.println("\n");
	}

	/**
	 * adds a new item to the inventory
	 *
	 * @return items id
	 */
	public int addNewItem() {
		InventoryItem item = new InventoryItem();
		int id = StreamIO.readInt("Inventory Id: ");
		item.setName(StreamIO.readString("Inventory Items name: "));
		item.setDescription(StreamIO.readString("Inventory Items description: "));
		item.setQuality(StreamIO.readInt("Inventory Items Quality: "));
		item.setQuality(StreamIO.readInt("Inventory Items Quantity: "));

		//add parts
		item = addParts(item);

		item.setID(id);
		items.add(item);

		return id;

	}

	/**
	 * addsParts to an inventory item
	 * @param item
	 * @return
	 */
	public InventoryItem addParts(InventoryItem item) {
		if (StreamIO.readString("Add Parts (y)es [n]o: ").equals("y")) {
			boolean addParts = true;
			while (addParts) {
				InventoryItem part = getItemByID(StreamIO.readInt("Inventory id of part: ", 1, 2));
				if (part != null) {
					item.addPart(part, 1);
					System.out.println("Part Added");
				} else {
					System.out.println("Part not found");
				}
				if (StreamIO.readInt("Add more parts? (1)Yes (2)no: ", 1, 2) == 2) {
					addParts = false;
				}
			}
		}
		return item;

	}

	/**
	 * adds a new product to the inventory
	 * @param item  the item to be promoted to product
	 */
	public void addNewProduct(InventoryItem item) {
		Product newProduct = new Product();
		int productID = StreamIO.readInt("Product id: ");
		newProduct.setID(productID);
		newProduct.setItem(item);

		products.add(newProduct);
	}

	/**
	 * edits an inventory item
	 */
	public void edit() {
		int id;
		printInventory();
		id = StreamIO.readInt("Which item would you like to edit: ");
		InventoryItem item = getItemByID(id);
		if (item != null) {
			item.modify();
			addParts(item);
		}

	}

	/**
	 * orders a product
	 */
	public void placeOrder() {
		printProducts();
		int id = StreamIO.readInt("Which product would you like to add order too?: ");
		int amount = StreamIO.readInt("How many would you like to add to order?: ");
		getProductByID(id).placeOrder(amount);
	}

	/**
	 * returns the item with id
	 * @param id id of item to return.
	 * @return  InventoryItem that has the id
	 */
	public InventoryItem getItemByID(int id) {
		for (InventoryItem i : items) {
			if (i.getID() == id) {
				return i;
			}
		}
		return null;
	}

	/**
	 * returns the item with id
	 * @param id id of the product to return
	 * @return  Product that has the id
	 */
	public Product getProductByID(int id) {
		for (Product p : products) {
			if (p.getID() == id) {
				return p;
			}
		}
		return null;
	}

	/**
	 * grabs the next product id
	 * @return
	 */
	public int nextProductID() {
		int id = 0;
		if (products != null) {
			for (Product p : products) {
				if (p.getID() > id) {
					id = p.getID();
				}
			}
		}
		return ++id;
	}

	/**
	 * grabs the next inventory id
	 * @return
	 */
	public int nextInventoryID() {
		int id = 0;
		if (items != null) {
			for (InventoryItem i : items) {
				if (i.getID() > id) {
					id = i.getID();
				}
			}
		}
		return ++id;
	}

	/**
	 * returns products linked list
	 * @return products
	 */
	public LinkedList<Product> getProducts() {
		return products;
	}

	/**
	 * gets inventory linked list
	 * @return inventory
	 */
	public LinkedList<InventoryItem> getInventory() {
		return items;
	}

	/**
	 * imports items from an xml file
	 */
	public void importItems() {
		LinkedList<Export> invItems = new LinkedList<Export>();
		Export temp = new Export();
		boolean stop = false;
		try {
			XMLDecoder d = new XMLDecoder(new BufferedInputStream(new FileInputStream("inventory.xml")));
			for (int i = 0; i < 100 && stop == false; i++) {
				temp = (Export) d.readObject();
				invItems.add(temp);
				items.add(temp.getItem());
			}
			d.close();
		} catch (IOException e) {
		} catch (ArrayIndexOutOfBoundsException e) {
			stop = true;
		}

		//second "linking" pass
		InventoryItem tempItem = new InventoryItem();
		for (Export e : invItems) {
			tempItem = getItemByID(e.getItem().getID());
			for (int[] i : e.getParts()) {
				tempItem.addPart(getItemByID(i[0]), i[1]);
			}
		}

	}

	/**
	 * imports products from an xml file
	 */
	public void importProducts() {
		ExportProduct temp = new ExportProduct();
		Product tempProduct;
		boolean stop = false;
		try {
			XMLDecoder d = new XMLDecoder(new BufferedInputStream(new FileInputStream("products.xml")));
			for (int i = 0; i < 100 && stop == false; i++) {
				temp = (ExportProduct) d.readObject();
				tempProduct = new Product();
				tempProduct.setID(temp.getPid());
				tempProduct.setItem(getItemByID(temp.getId()));
				tempProduct.setBackOrder(temp.getBackorder());
				products.add(tempProduct);
			}
			d.close();
		} catch (IOException e) {
		} catch (ArrayIndexOutOfBoundsException e) {
			stop = true;
		}
	}

	/**
	 * grabs an element from an element in dom xml representation
	 * @param prElmnt Element containing value
	 * @param name  elements tag name
	 * @return  String of nodes value
	 */
	private String getElement(Element prElmnt, String name) {
		NodeList elementList = prElmnt.getElementsByTagName(name);
		NodeList id = ((Element) elementList.item(0)).getChildNodes();
		return ((Node) id.item(0)).getNodeValue();
	}

	/**
	 * exports inventory and products to file
	 */
	public void export() {
		exportInventory();
		exportProducts();
	}

	/**
	 * exports inventory to xml files
	 */
	private void exportInventory() {
		try {
			XMLEncoder enc = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("inventory.xml")));

			for (final InventoryItem i : items) {
				Export item = new Export(i, i.getParts());
				enc.writeObject(item);
			}
			enc.close();
		} catch (IOException e) {
		}

	}

	/**
	 * exports products to an xml file
	 */
	private void exportProducts() {

		try {
			XMLEncoder enc = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("products.xml")));

			for (final Product p : products) {
				enc.writeObject(new ExportProduct(p.getItem().getID(), p.getID(), p.getBackOrder()));
			}
			enc.close();
		} catch (IOException e) {
		}
	}
}
